package main

import (
	// "encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"

	//"github.com/ceph/go-ceph/rados"
	"gitee.com/czy233/go-ceph/rados"
)

type Ceph struct {
	ioctx *rados.IOContext
	conn  *rados.Conn
}

type Obj struct {
	ID   string `json:"ID"`
	Hash string `json:"Hash"`
}

//以HTTP的形式从fabric获得对象的默克根
func GethashFromHttp(obj Transaction) (data []byte) {
	IP := "10.10.9.20"
	//IP := ClusterIp(int(obj.From))
	data = make([]byte, 4096)
	data = ReadFromfabric(IP, ClusterPort, strconv.Itoa(int(obj.From))+"_"+string(obj.Hash))
	if data == nil {
		log.Println("cluster", Cluster, ":", "查询失败", string(obj.Hash), ": http error")
	} else {
		log.Println("cluster", Cluster, ":", "查询成功", string(obj.Hash))
	}
	return
}

//以HTTP的形式从fabric获得对象的默克根
func ReadFromfabric(IP string, port int, obj string) []byte {
	url := "http://" + IP + ":" + strconv.Itoa(port) + "/get?ID=" + obj
	log.Println("cluster", Cluster, ":", url)
	resp, err := http.Get(url)
	if err != nil {
		return nil
	}
	defer resp.Body.Close()
	ret, err := ioutil.ReadAll(resp.Body)
	// var data Obj
	// json.Unmarshal(ret, &data)
	log.Println("cluster", Cluster, ": 接收到哈希", obj, ret)
	if err != nil {
		return nil
	}
	// return []byte(data.Hash)
	return ret
}

//以HTTP的形式从其他机构获得对象的默克证明
func (c *Ceph) GetMerkleRootFromHttp(obj Transaction, offset int) (data []byte) {
	// IP := "10.10.9.20"
	IP := ClusterIp(int(obj.From))
	data = make([]byte, 4096)
	data = ReadFromClusters(IP, ClusterPort, string(obj.Hash), offset)
	if data == nil {
		log.Println("cluster", Cluster, ":", "抽查失败", string(obj.Hash), ": http error")
	} else {
		log.Println("cluster", Cluster, ":", "抽查成功", string(obj.Hash))
	}
	return
}

//以HTTP的形式从其他机构获得对象的默克证明
func ReadFromClusters(IP string, port int, obj string, offset int) []byte {
	url := "http://" + IP + ":" + strconv.Itoa(port) + "/check?oid=" + obj + "&off=" + strconv.Itoa(offset)
	log.Println("cluster", Cluster, ":", url)
	resp, err := http.Get(url)
	if err != nil {
		return nil
	}
	defer resp.Body.Close()
	ret, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil
	}
	return ret
}

//获取本地数据
func (c *Ceph) getBlockData(oid string) (data []byte) {
	data = make([]byte, 4096)
	ret, err := c.ioctx.Read(oid, data, 0)
	if err != nil {
		log.Println("cluster", Cluster, ":", "error when read obj:", err)
		return
	}
	if ret != 4096 {
		log.Println("cluster", Cluster, ":", "error when read obj")
	}
	return
}

//写本地数据 上链
func (c *Ceph) writedatafull(oid string, data []byte) error {
	err := c.ioctx.WriteFullWithPutHash(oid, data)
	if err != nil {
		log.Println("cluster", Cluster, ":", "error when fully write obj:", err)
		return err
	}
	return nil
}

//写本地数据 不上链
func (c *Ceph) writedatapartial(oid string, data []byte) error {
	err := c.ioctx.WriteFull(oid, data)
	if err != nil {
		log.Println("cluster", Cluster, ":", "error when partially write obj:", err)
		return err
	}
	return nil
}

// 删除本地数据
func (c *Ceph) deletedata(oid string) {
	err := c.ioctx.Delete(oid)
	if err != nil {
		log.Println("cluster", Cluster, ":", "error when delete obj:", err)
	}
}

// 生成ceph接口
func (c *Ceph) CephInit() {
	conn, err := rados.NewConn()
	if err != nil {
		fmt.Println("error when invoke a new connection:", err)
	}

	err = conn.ReadDefaultConfigFile()
	if err != nil {
		fmt.Println("error when read default config file:", err)
	}

	err = conn.Connect()
	if err != nil {
		fmt.Println("error when connect:", err)
	}

	fmt.Println("connect ceph cluster ok!")

	ioctx, err := conn.OpenIOContext("testbench")
	if err != nil {
		fmt.Println("error when open IO context:", err)
	}
	c.ioctx = ioctx
	c.conn = conn
}

func (c *Ceph) Free() {
	c.conn.Shutdown()
}
